{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Conventions"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This tutorial lists some of the most important conventions and assumptions used in PorePy.\n",
    "\n",
    "Specifically, we cover conventions for:\n",
    "* Geometry\n",
    "* Boundaries\n",
    "* Equations\n",
    "* Apertures\n",
    "* Coupling between dimensions"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Geometry\n",
    "Normal vectors are defined once for each face and can be accessed through `sd.face_normals` for a subdomain, `sd`. These vectors are weighted with the face area, meaning that the area of a face can be found by taking the norm of its normal vector.\n",
    "\n",
    "For a subdomain grid sd, the field `sd.cell_faces` is the discrete divergence: \n",
    "* It has dimensions (number of faces) $\\times$ (number of cells)\n",
    "* It is nonzero only for the neighboring faces of any given cell\n",
    "* The value is positive if the normal vector of the face points outwards from the cell and negative otherwise.\n",
    "\n",
    "See [this](./grid_topology.ipynb) tutorial for a demonstrations of the aforementioned.\n",
    "\n",
    "\n",
    "This can be used to obtain the outwards pointing normal vector of a cell. We simply multiply with the value ($\\pm 1$) of sd.cell_faces. For instance, for cell `c` and face `f` we have\n",
    "\n",
    "`outward_normal = sd.cell_faces[f, c] * sd.face_normals[:, f]`\n",
    "### Local coordinates and internal boundaries \n",
    "In [mixed-dimensional grids](./mixed_dimensional_grids.ipynb) (TODO: Move there? Or create fracture deformation tutorial?), fractures define internal boundaries for the matrix.\n",
    "Each fracture is assigned a local basis with a normal vector and one or two tangential vectors for ambient dimension of 2 and 3, respectively. \n",
    "The fracture's normal vector coincides with the outwards normal vector of the matrix on the \"j side\"/\"left side\" of the fracture (the other side is referred to as the \"k side\" or the \"right side\").\n",
    "The fracture is assigned a `TangentialNormalProjection` with methods to rotate between global and local coordinates.\n",
    "\n",
    "In some settings, it is important to distinguish between the two sides of a fracture.\n",
    "This information is contained in the `sign_of_mortar_sides` method of the `MortarGrid` representing the fracture-matrix interface.\n",
    "The method returns a matrix with $-1$ and $+1$ entries corresponding to the j and k side, respectively.\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## External boundaries\n",
    "### Flow\n",
    "Outflow values are considered positive for Neumann type boundary conditions, i.e. outward pointing normal vectors are assumed.\n",
    "\n",
    "On inner boundaries, a positive mortar flux $\\lambda$ implies flow from the higher-dimensional to the lower-dimensional domain.\n",
    "### Mechanics\n",
    "Mechanical boundary condtions are always given in global coordinates. \n",
    "For Dirichlet boundary condition values, we prescribe the displacement values directly without regarding the normal vector. \n",
    "For a 2d  domain, this means that a prescribed boundary value of $\\mathbf{u}_b = [1, -2]$ signifies a unitary displacement to the right, and downwards with magnitude 2. \n",
    "Similarly, $\\sigma\\cdot \\mathbf{n} = [-1, 0]$ implies a unitary force to the left.\n",
    "\n",
    "Displacements defined on inner boundaries are also in global coordinates.\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Equations\n",
    "### Momentum balance\n",
    "The momentum balance equation within PorePy follows the convention of positive tensile stress. \n",
    "In practice this means that the equation is described by the following formulation:\n",
    "\n",
    "$\\frac{\\partial^2 u}{\\partial t^2} = \\nabla \\cdot \\sigma (\\epsilon (u)) + q$,\n",
    "\n",
    "where $u$ is displacement, $\\sigma(\\epsilon(u))$ is the stress tensor and $q$ is the body force.\n",
    "Usually the stress tensor is related to displacement through Hooke's law and the strain-displacement relation for small deformations:\n",
    "\n",
    "$\\sigma(\\epsilon(u)) = C : \\epsilon(u) = C : \\frac{1}{2} (\\nabla u + (\\nabla u)^T)$,\n",
    "\n",
    "where $C$ denotes the stiffness tensor.\n",
    "\n",
    "### Spatial dimensions\n",
    "PorePy allows simulations in 3, 2 and, for some cases, 1 dimensions. We denote the highest dimension by `nd`. If `nd`$<3$, the units of the equation change accordingly - e.g. kg/s/m for a `nd`=2 mass balance. This implies that the units of parameters entering the equation remain unchanged. For instance, the mass density is still kg/m$^3$, not kg/m$^2$.\n",
    "\n",
    "### Nondimensionalization\n",
    "Currently, most equations and variables have their natural physical units.\n",
    "The exceptions are the contact mechanics equations and the contact traction, which are nondimensionalized using a characteristic traction."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Apertures\n",
    "In our mixed-dimensional models we denote the thickness of the fractures by the term `aperture` [m], denoted by $a$. \n",
    "\n",
    "Volumes [m$^3$] of fracture or intersection cells are computed through their specific volumes. \n",
    "In any given dimension d, this is the volume of the cell per d-dimensional measure. \n",
    "In 2d, it is the volume per area, and has dimensions [m$^3/$m$^2$] = [m]. \n",
    "The measure is a line measure for 1d intersection lines, and the specific volume thus has the dimensions [m$^3/$m] = [m$^2$]. \n",
    "In general, the dimensions are [m$^{3-d}$], where d is the dimension of the subdomain in question.\n",
    "The full volume is always the product of the d-dimensional cell volume and the specific volume.\n",
    "\n",
    "`volumes = g.cell_volumes * specific_volumes` $\\quad$ [m$^3$]\n",
    "\n",
    "This implies that some parameters should be weighted by the specific volumes. \n",
    "This holds for tangential permeability, volumetric source terms and several other parameters. \n",
    "To be clear, the permeabilities specified within and between subdomains are absolute, that is, no aperture scaling of permeabilities takes place inside the code."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
